import React, { useEffect, useRef } from "react";
import { Graph, Model } from "@antv/x6";
import { DagreLayout } from "@antv/layout";
import "./index.model.css";

import { useDigitalEmployeeStore } from "@/store/employee";

type NodeData = {
  id: string;
  label: string;
  name?: string;
  status?: string; // "success" | "error" | "wait"
  icon: string;
};

type EdgeData = {
  source: string;
  target: string;
};

type FlowGraphProps = {
  nodeflowsJson: string;
};

const FlowGraph: React.FC<FlowGraphProps> = ({ nodeflowsJson }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const graphRef = useRef<Graph | null>(null);

  const getIconPath = useDigitalEmployeeStore((state) => state.getIconPath);

  // 虚线流动动画
  const animateDashedLines = (graph: Graph) => {
    let offset = 0;

    const step = () => {
      offset -= 1;
      graph.getEdges().forEach((edge) => {
        const attrs = edge.getAttrs();
        const dash = attrs?.line?.strokeDasharray;
        if (dash) {
          edge.setAttrs({
            line: {
              strokeDashoffset: offset,
            },
          });
        }
      });
      requestAnimationFrame(step);
    };

    requestAnimationFrame(step);
  };

  useEffect(() => {
    if (!containerRef.current) return;

    let parsed;
    try {
      parsed = JSON.parse(nodeflowsJson);
    } catch (e) {
      console.error("nodeflowsJson 解析失败:", e);
      return;
    }

    const nodes: NodeData[] = parsed.nodes || [];
    nodes.map((node) => {
      const runStatusMap = {
        success: 0,
        wait: 1,
        error: 3,
      };

      if (node.status && Object.keys(runStatusMap).includes(node.status)) {
        try {
          const newicon = JSON.parse(node.icon);
          newicon.run_status =
            runStatusMap[node.status as keyof typeof runStatusMap];
          node.icon = JSON.stringify(newicon);
        } catch (e) {
          console.error("Icon parsing failed for node:", node.id, e);
        }
      }
    });

    console.log(nodes, "nodes 解析");
    const edges: EdgeData[] = parsed.edges || [];

    const modelData: Model.FromJSONData = {
      nodes: nodes.map((n) => ({
        id: n.id,
        shape: "image",
        width: 100,
        height: 100,
        label: n.label,
        attrs: {
          image: {
            "xlink:href": getIconPath(n.icon),
            width: 100,
            height: 100,
          },
          label: {
            text: n.name,
            fill: "#fff",
            fontSize: 14,
            fontWeight: "bold",
            refX: "50%",
            refY: "100%",
            y: 10,
            textAnchor: "middle",
            textVerticalAnchor: "top",
          },
        },
      })),
      edges: edges.map((e) => ({
        source: e.source,
        target: e.target,
        attrs: {
          line: {
            stroke: "#A2B1C3",
            strokeWidth: 2,
            strokeDasharray: "6 3",
            strokeDashoffset: 0,
            targetMarker: {
              name: "classic",
              size: 6,
            },
          },
        },
      })),
    };

    if (!graphRef.current) {
      graphRef.current = new Graph({
        container: containerRef.current,
        panning: true,
        mousewheel: true,
        grid: false,
      });
    }

    const graph = graphRef.current;

    const dagreLayout = new DagreLayout({
      type: "dagre",
      rankdir: "LR",
      align: "UL",
      ranksep: 60,
      nodesep: 30,
    });

    const layouted = dagreLayout.layout(modelData as any);
    graph.fromJSON(layouted);
    graph.zoomToFit({ padding: 20, maxScale: 1 });

    // 启动动画
    animateDashedLines(graph);

    // 2.5秒后设为实线，根据 source 节点状态决定颜色
    const timer = setTimeout(() => {
      const statusColorMap: Record<string, string> = {
        success: "#52c41a",
        error: "#A2B1C3",
        wait: "#A2B1C3",
        pending: "#A2B1C3", // 默认灰
      };

      graph.getEdges().forEach((edge) => {
        const sourceId = edge.getSourceCellId();
        const sourceNode = nodes.find((n) => n.id === sourceId);
        const status = sourceNode?.status || "pending";

        const strokeColor = statusColorMap[status] || "#A2B1C3";

        edge.setAttrs({
          line: {
            stroke: strokeColor,
            strokeWidth: 2,
            strokeDasharray: "",
            strokeDashoffset: 0,
            targetMarker: {
              name: "classic",
              size: 6,
            },
          },
        });
      });
    }, 2500);

    return () => {
      graph.clearCells();
      clearTimeout(timer);
    };
  }, [nodeflowsJson]);

  return (
    <div
      className="x6-graph-wrapper"
      ref={containerRef}
      style={{ width: "100%", height: "100%" }}
    />
  );
};

export default FlowGraph;
